package com.leadingsoft.test;

import java.awt.BorderLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;

import javax.swing.JFrame;
import javax.swing.JPanel;

import org.cef.CefApp;
import org.cef.CefApp.CefVersion;
import org.cef.CefClient;
import org.cef.CefSettings;
import org.cef.OS;
import org.cef.browser.CefBrowser;
import org.cef.browser.CefFrame;
import org.cef.browser.CefMessageRouter;
import org.cef.browser.CefRequestContext;
import org.cef.handler.CefDisplayHandlerAdapter;
import org.cef.handler.CefLoadHandlerAdapter;
import org.cef.handler.CefRequestContextHandlerAdapter;
import org.cef.network.CefCookieManager;

import com.leadingsoft.core.AddLibraryDir;
import com.leadingsoft.test.dialog.DownloadDialog;
import com.leadingsoft.test.handler.AppHandler;
import com.leadingsoft.test.handler.ContextMenuHandler;
import com.leadingsoft.test.handler.DragHandler;
import com.leadingsoft.test.handler.JSDialogHandler;
import com.leadingsoft.test.handler.KeyboardHandler;
import com.leadingsoft.test.handler.MessageRouterHandler;
import com.leadingsoft.test.handler.MessageRouterHandlerEx;
import com.leadingsoft.test.handler.RequestHandler;
import com.leadingsoft.test.ui.ControlPanel;
import com.leadingsoft.test.ui.MenuBar;
import com.leadingsoft.test.ui.StatusPanel;

public class MainFrame extends JFrame {
	private static final long serialVersionUID = -2295538706810864538L;

	public static void main(String[] args) {
		// 在Linux上默认启用OSR模式
		// 在Windows和Mac OS X.上默认禁用
		boolean osrEnabledArg = OS.isLinux();
		boolean transparentPaintingEnabledArg = false;
		String cookiePath = null;
		for (String arg : args) {
			arg = arg.toLowerCase();
			if (!OS.isLinux() && arg.equals("--off-screen-rendering-enabled")) {
				osrEnabledArg = true;
			} else if (arg.equals("--transparent-painting-enabled")) {
				transparentPaintingEnabledArg = true;
			} else if (arg.startsWith("--cookie-path=")) {
				cookiePath = arg.substring("--cookie-path=".length());
				File testPath = new File(cookiePath);
				if (!testPath.isDirectory() || !testPath.canWrite()) {
					System.out.println("Can't use " + cookiePath
							+ " as cookie directory. Check if it exists and if it is writable");
					cookiePath = null;
				} else {
					System.out.println("Storing cookies in " + cookiePath);
				}
			}
		}
		System.out.println("Offscreen rendering " + (osrEnabledArg ? "enabled" : "disabled"));
		// 主机保持所有信息对于正在显示的嵌入式浏览器
		// 窗口
		final MainFrame frame = new MainFrame(osrEnabledArg, transparentPaintingEnabledArg, cookiePath, args);
		frame.addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				CefApp.getInstance().dispose();
				frame.dispose();
			}
		});
		frame.setSize(800, 600);
		frame.setVisible(true);
	}

	private final CefClient client;
	private String errorMsg = "";
	private final CefBrowser browser;
	private ControlPanel controlPane;
	private StatusPanel statusPanel;
	private final CefCookieManager cookieManager;

	public MainFrame(boolean osrEnabled, boolean transparentPaintingEnabled, String cookiePath, String[] args) {
		AddLibraryDir.addDLL();
		// 1、CefApp是JCEF的切入点
		// 如果您想处理任何与chromium或CEF的交互或设置属性
		// 可以通过使用原生语言将参数传递给CefApp
		CefSettings settings = new CefSettings();
		settings.windowless_rendering_enabled = osrEnabled;
		// 可以尝试加载URL为空白用来查看背景颜色
		settings.background_color = settings.new ColorType(100, 255, 242, 211);
		CefApp myApp = CefApp.getInstance(args, settings);
		CefVersion version = myApp.getVersion();
		System.out.println("Using:\n" + version);
		// 我们可以注册自己的AppHandler 因为我们希望添加自己的处理方案来处理程序
		// 例如输入"search:something on the web"，就可以自己去www.google.com上面搜索结果
		CefApp.addAppHandler(new AppHandler(args));
		// 通过调用本地的createClient()方法将初始化JCEF/CEF
		// 可以创建一个或多个CefClient实例
		client = myApp.createClient();
		// 可以将处理程序配置给CefClient
		// 每个处理程序负责处理不同的信息（例如键盘输入）
		// 对于每个处理程序（具有不止一种方法）都存在处理类
		// 所以你不需要重写你不感兴趣的方法
		DownloadDialog downloadDialog = new DownloadDialog(this);
		client.addContextMenuHandler(new ContextMenuHandler(this));
		client.addDownloadHandler(downloadDialog);
		client.addDragHandler(new DragHandler());
		client.addJSDialogHandler(new JSDialogHandler());
		client.addKeyboardHandler(new KeyboardHandler());
		client.addRequestHandler(new RequestHandler(this));
		// 除了正常的处理程序实例之外
		// 我们还可以注册MessageRouter，可以应对JS的调用（JavaScript绑定）
		// 当我们使用默认配置时，会使用"CEFQuQuy"和"CEFQuyReCuffe"作为JavaScript绑定方法
		CefMessageRouter msgRouter = CefMessageRouter.create();
		msgRouter.addHandler(new MessageRouterHandler(), true);
		msgRouter.addHandler(new MessageRouterHandlerEx(client), false);
		client.addMessageRouter(msgRouter);
		// 将CefDisplayHandler覆盖为嵌套匿名类
		// 更新地址字段，也就是面板的标题
		// 用于更新浏览器底部的状态栏
		client.addDisplayHandler(new CefDisplayHandlerAdapter() {
			@Override
			public void onAddressChange(CefBrowser browser, CefFrame frame, String url) {
				controlPane.setAddress(browser, url);
			}
			@Override
			public void onTitleChange(CefBrowser browser, String title) {
				setTitle(title);
			}
			@Override
			public void onStatusMessage(CefBrowser browser, String value) {
				statusPanel.setStatusText(value);
			}
		});
		// 禁用/启用导航按钮并显示PrGress栏(表示我们网站的负载状态)
		// 重写CefLoadHandler作为嵌套匿名类。重写Load处理程序负责处理（加载）错误。
		// 例如，如果你导航到一个不存在的URL
		// 浏览器将显示一条错误消息
		client.addLoadHandler(new CefLoadHandlerAdapter() {
			@Override
			public void onLoadingStateChange(CefBrowser browser, boolean isLoading, boolean canGoBack,
					boolean canGoForward) {
				controlPane.update(browser, isLoading, canGoBack, canGoForward);
				statusPanel.setIsInProgress(isLoading);
				if (!isLoading && !errorMsg.isEmpty()) {
					browser.loadString(errorMsg, controlPane.getAddress());
					errorMsg = "";
				}
			}
			@Override
			public void onLoadError(CefBrowser browser, CefFrame frame, ErrorCode errorCode, String errorText,
					String failedUrl) {
				if (errorCode != ErrorCode.ERR_NONE && errorCode != ErrorCode.ERR_ABORTED) {
					errorMsg = "<html><head>";
					errorMsg += "<title>Error while loading</title>";
					errorMsg += "</head><body>";
					errorMsg += "<h1>" + errorCode + "</h1>";
					errorMsg += "<h3>Failed to load " + failedUrl + "</h3>";
					errorMsg += "<p>" + (errorText == null ? "" : errorText) + "</p>";
					errorMsg += "</body></html>";
					browser.stopLoad();
				}
			}
		});
		// 在显示任何内容之前，我们需要通过CefClient创建CefBrowser
		// 每个CEFCube都可以创建一对多的浏览器实例。
		// 如果指定了Cookie的存放路径。可以使用CefCookieManager加载Cookies
		CefRequestContext requestContext = null;
		if (cookiePath != null) {
			cookieManager = CefCookieManager.createManager(cookiePath, false);
			requestContext = CefRequestContext.createContext(new CefRequestContextHandlerAdapter() {
				@Override
				public CefCookieManager getCookieManager() {
					return cookieManager;
				}
			});
		} else {
			cookieManager = CefCookieManager.getGlobalManager();
		}
		browser = client.createBrowser("http://www.baidu.com", osrEnabled, transparentPaintingEnabled, requestContext);
		// Last but not least we're setting up the UI for this example implementation.
		getContentPane().add(createContentPanel(), BorderLayout.CENTER);
		MenuBar menuBar = new MenuBar(this, browser, controlPane, downloadDialog, cookieManager);
		menuBar.addBookmark("Binding Test", "client://tests/bindingtest.html");
		menuBar.addBookmark("Binding Test 2", "client://tests/bindingtest2.html");
		menuBar.addBookmark("Download Test", "http://cefbuilds.com");
		menuBar.addBookmark("Login Test (username:pumpkin, password:pie)",
				"http://www.colostate.edu/~ric/protect/your.html");
		menuBar.addBookmark("Certificate-error Test", "https://www.k2go.de");
		menuBar.addBookmark("Resource-Handler Test", "http://www.foo.bar/");
		menuBar.addBookmark("Resource-Handler Set Error Test", "http://seterror.test/");
		menuBar.addBookmark("Scheme-Handler Test 1: (scheme \"client\")", "client://tests/handler.html");
		menuBar.addBookmark("Scheme-Handler Test 2: (scheme \"search\")", "search://do a barrel roll/");
		menuBar.addBookmark("Spellcheck Test", "client://tests/spellcheck.html");
		menuBar.addBookmark("LocalStorage Test", "client://tests/localstorage.html");
		menuBar.addBookmark("Transparency Test", "client://tests/transparency.html");
		menuBar.addBookmarkSeparator();
		menuBar.addBookmark("javachromiumembedded", "https://bitbucket.org/chromiumembedded/java-cef");
		menuBar.addBookmark("chromiumembedded", "https://bitbucket.org/chromiumembedded/cef");
		setJMenuBar(menuBar);
	}
	private JPanel createContentPanel() {
		JPanel contentPanel = new JPanel(new BorderLayout());
		controlPane = new ControlPanel(browser);
		statusPanel = new StatusPanel();
		contentPanel.add(controlPane, BorderLayout.NORTH);
		// 4) By calling getUIComponen() on the CefBrowser instance, we receive
		// an displayable UI component which we can add to our application.
		contentPanel.add(browser.getUIComponent(), BorderLayout.CENTER);
		contentPanel.add(statusPanel, BorderLayout.SOUTH);
		return contentPanel;
	}
}
